home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / basic / ahnuts.exe / AHNUTS.ASM < prev    next >
Encoding:
Assembly Source File  |  1992-06-21  |  18.0 KB  |  342 lines

  1. page 64,132
  2. ; ***************************************************************************
  3. ;   AHNUTS.ASM
  4. ;   VERSION 1.0, 6/20/1992
  5. ;   Released to the PUBLIC DOMAIN by the author: Lewis E. Balentine
  6. ; ***************************************************************************
  7. ;
  8. ; --------------- DOS directory functions for MicroSoft PDS -----------------
  9. ;   I am so flustrated with what MS calls "profesional" I could scream !!!!!
  10. ;   Among my list of complaints is the inability to read subdirectory names,
  11. ;   files sizes and dates. This file is a direct result of that flustration. 
  12. ;
  13. ;   I ordered a third party library so I would have those functions. Its
  14. ;   directory functions were very fancy ... not what I wanted. All I 
  15. ;   really want is a simple implimentation of DOS findfirst and findnext 
  16. ;   functions.
  17. ;
  18. ;   All else has failed... ... ... Ah Nuts ! ! ! ----------------------------
  19. ;
  20. ; WARNING #1: ASSEMBLER code is not my cup of tea. This took me a solid 
  21. ;   week of screaming and nashing of teeth as I dug through various manuals
  22. ;   with each line of code. Thus there is very little error handling and none
  23. ;   for DOS critical errors (you will need to use PDS's ON ERROR function).
  24. ;   I chose to use the "KISS" method. Thus no equates, macros, defines or 
  25. ;   stack variables (except those passed by PDS) are used. I have tried to
  26. ;   put in enough comments that I could figure out what it was that I did a
  27. ;   week later. Thus someone else should be able to figure it out. (I have
  28. ;   a very short memory refresh).
  29. ;
  30. ; WARNING #2: This is written for use with far strings only. I have never
  31. ;   installed the near string library and haven't any idea what will happen
  32. ;   with near strings.
  33. ;
  34. ; WARNING #3: What you see is what you get. There is no warranty exspressed,
  35. ;   implied or otherwise.
  36. ;
  37. ; REFFERENCES:
  38. ;   The following manuals/books were used in developing this code:
  39. ;   Basic Programer's Guide version 7.0 (c)1989,1988,1887, Microsoft
  40. ;   Macro Assembler 5.0 Programers Guide (c)1987, Microsoft
  41. ;   Macro Assembler 5.1 Update (c)1987, Microsoft
  42. ;   Disk Operating System Ver 3.3 Technical Reference (c)1987,1985, IBM
  43. ;   The 8086 Book (c)1980, Osborne/McGraw-Hill, Russell Rector, George Alexy
  44. ;
  45. ; DEBUGGING:
  46. ;   As much as I hate to admit it, this module was debugged using Microsoft
  47. ;   Codeview (because nothing else would work with PDS exe's). I have three
  48. ;   major problems with Codeview:
  49. ;   1)  Although I have PDS 7.1, Quick "C" and Masm 5.1 the only manual I
  50. ;       I have for CV came with MASM 5.0 and it is out of date!
  51. ;   2)  I can not find a way to load the asm source code when debugging
  52. ;       a mixed PDS and ASM executible.
  53. ;   3)  How can anybody get anything done in assembly without a stack window.
  54. ;       A extra memory window is a poor substitute for the real thing.
  55. ;
  56. ; LINKING with PDS:
  57. ;   masm ahnuts.asm, ahnuts.obj, ahnuts.lst,;
  58. ;   link /Q ahnuts.obj qbx.lib, ahnuts.qlb, , qbxqlb.lib;
  59. ;   lib ahnuts.lib +ahnuts.obj+qbx.lib;
  60. ;   qbx /l ahnuts.qlb  
  61. ;   (at this point you are on your own ..... have fun!)
  62. ;-----------------------------------------------------------------------------
  63. .lall                                   ; list all code generated
  64. extrn   STRINGLENGTH:far                ; Declare external functions 
  65. extrn   STRINGASSIGN:far                ; provided by PDS for variable
  66. extrn   STRINGRELEASE:far               ; length string operations.
  67. ;-----------------------------------------------------------------------------
  68. .model medium,basic                     ; PDS Prg Guide pg 476.
  69. .stack
  70. ;-----------------------------------------------------------------------------
  71. .data
  72. olddtao dw      0                       ; PDS's Disk Transfer Area offset
  73. olddtas dw      0                       ; PDS's Disk Transfer Area segment
  74. ourdta  db      21 dup (0)              ; Our DTA, 21 Bytes for DOS
  75. ouratr  db      0                       ;        , file atribute
  76. ourtime dw      0                       ;        , file time
  77. ourdate dw      0                       ;        , file date
  78. ourlosz dw      0                       ;        , low word of file size
  79. ourhisz dw      0                       ;        , high word of file size 
  80. ourname db      13 dup (0)              ;        , file name
  81.         db      0                       ; ... Just say this is insurance.
  82. work    db      130 dup (0)             ; Our string space.
  83. strdsc  dd      0                       ; Our return string descriptor.
  84. found   dw      0                       ; Used to determine previous call.
  85. ourerr  dw      0                       ; Store our exit error code.
  86.  
  87. .code
  88. ;-----------------------------------------------------------------------------
  89. ; FindFile
  90. ; INPUT:
  91. ; Function takes 2 parameters, a string and a integer.
  92. ; The first call should contain a search mask for the file name and a
  93. ; value for the search atribute.
  94. ;
  95. ; The second call should contain a null string for the file mask. The 
  96. ; passed attribute will be ignored on the second call.
  97. ;
  98. ; RETURN:
  99. ; If a matching file is found the function returns a variable length
  100. ; string with the file name. On error a NULL string is returned.
  101. ;
  102. ; BASIC: (PDS 7.1 with far strings enabled)
  103. ;   Declare Function FindFile$(spec$, atribut%)
  104. ;   ... Thus on entry the stack will look like this
  105. ;            spec string        2 bytes (near pointer to descriptor)
  106. ;            atribute           2 bytes (near pointer to 2 byte integer)
  107. ;            return address     4 bytes (far return)
  108. ;----------------------------------------------------------------------
  109. FindFile proc uses   si di, spec , atrib    ; Per PDS prog guide pg. 478,
  110.     ; push      bp                          ; preserve si di ss ds bp and
  111.     ; mov       bp,sp                       ; direction flag.
  112.     ; push      si                          ; We use PDS's DS and SS.
  113.     ; push      di                          ; "proc uses" directive handles
  114.     ; ... the instructions above are from   ; the BP  SP registers.
  115.     ; ... the Assembler directive "uses"    ; Flags are saved below.
  116.  
  117.         pushf                           ; First let us save the flags.
  118.         mov     ourerr,0                ; Clear our error storage.
  119.  
  120.         ; This routine uses calls to DOS FindFirst and FindNext function,
  121.         ; in either case we need to save the existing DTA and replace it
  122.         ; with our own static data area. 
  123.         mov     ah,2Fh                  ; DOS function: Get DTA
  124.         int     21h                     ; Call DOS
  125.         mov     olddtao,bx              ; Save old dta offset.
  126.         mov     olddtas,es              ; Save old dta segment.
  127.         mov     dx, offset ds:ourdta    ; Set DS:DX to our DTA.
  128.         mov     ah, 1Ah                 ; DOS function: Set DTA
  129.         int     21h                     ; call DOS
  130.  
  131.         ; Now we need to know if this is new request.
  132.         ; First we need our string length. PDS provide's
  133.         ; a function for this purpose.
  134.         mov     ax, spec                ; ... Per PDS Prog Guide.
  135.         push    ax                      ; Push the string parameter pointer.
  136.         call    stringlength            ; Call PDS, length returned in AX
  137.         or      ax, ax                  ; If length <> 0 then
  138.         jnz     @F                      ; jump fwd to label @@, otherwise
  139.         jmp     findnext                ; jump to find next match file.
  140.  
  141.         ; We have allowed 128 bytes for those long network paths.
  142. @@:     cmp     ax, 128                 ; If spec is not too long then
  143.         jb      @F                      ; jump fwd to label @@, otherwise
  144.         mov     ax, -1                  ; define our error code and
  145.         jmp     exiter                  ; jump to exit with error.
  146.  
  147.         ; Now we assume we have a valid spec and need to move it to our
  148.         ; work area so we can append a zero byte. First we save the len.
  149. @@:     mov     found,0                 ; Release our flag.
  150.         mov     bx, ax                  ; Mov length to BX.
  151.         inc     bx                      ; Add 1 to length of string.
  152.         mov     work[bx],0              ; Store a zero to terminate string.
  153.         mov     ax, spec                ; Per PDS Prog Guide pg 495:
  154.         push    ds                      ; Get the string parameter pointer
  155.         push    ax                      ; and push it on the stack
  156.         xor     ax,ax                   ; Place zero in AX and push it
  157.         push    ax                      ; to indicate variable len string.
  158.         push    ds                      ; Push our Data Segment on stack.
  159.         mov     ax, offset ds:work      ; Get address of our string space
  160.         push    ax                      ; and push it on the stack.
  161.         dec     bx                      ; Sub 1 from length of string.
  162.         push    bx                      ; Push length of string on stack.
  163.         call    stringassign            ; Call PDS to move string.
  164.  
  165.         ; Now we set up the DOS call to find first.
  166.         ; DOS exspect the address of the spec in DS:DX and the 
  167.         ; 8 bit atribute in CX. 
  168.         ; With our 16 bit atribute the low byte holds the BIT spec we want
  169.         ; to match.
  170.         mov     bx, atrib               ; Get the DS offset of atribute.
  171.         mov     cx, [bx]                ; Get the value of atibute in CX.
  172.         xor     ch,ch                   ; Zero the top half.
  173.         mov     dx, offset ds:work      ; Address of our file mask.
  174.         mov     ax,4E00h                ; DOS FIND FIRST function.
  175.         int     21h                     ; Call DOS
  176.  
  177.         ; Error code (if carry flag set) will be returned in AX.
  178.         jnc     exitok                  ; If no error, format string, exit.
  179.         jmp     exiter                  ; Otherwise return Null String
  180.  
  181. findnext:   ; We come here on a repeat call to the routine.
  182.         mov     ax,found                ; We first check to see if
  183.         cmp     ax,0                    ; the first call found a file.
  184.         jnz     @F                      ; Jump over our error handler.
  185.         mov     ax,-2                   ; Define return error code.
  186.         jmp     exiter                  ; Exit with error.
  187. @@:     mov     ax,4F00h                ; DOS FIND NEXT function.
  188.         int     21h                     ; Call DOS
  189.  
  190.         ; Error code (if carry flag set) will be returned in AX.
  191.         jnc     exitok                  ; If no error, format string, exit.
  192.                                         ; Otherwise return Null String
  193. exiter: ; Uhhh ... we come here if we have a problem ...
  194.         ; ... And do we ever have a problem. MS neglected to explain how
  195.         ; to return a NULL string to PDS. I am going to take a wild guess
  196.         ; and try returning a string descriptor that has been processd by
  197.         ; stringrelease.
  198.         mov     ourerr,ax               ; Store AX as our exit error.
  199.         mov     ax,offset ds:strdsc     ; Push our string descriptor address
  200.         push    ax                      ; on the stack.
  201.         call    stringrelease           ; Make our string null (I hope).
  202.         jmp     exit                    ; Ok ... Now we can leave.
  203.  
  204. exitok: ; We jump here if we found what we are looking for
  205.         mov     ax,found                ; Set our flag. Just for the heck
  206.         inc     ax                      ; of it we shall keep track of
  207.         mov     found,ax                ; how many files we have found.
  208.  
  209.         ; Our DTA should now contain the information we desire.
  210.         ; We need to find the zero terminator for the file name.
  211.         cld                             ; Put the gear box in foward.
  212.         push    es                      ; Save ES.
  213.         push    ds                      ; Make sure ES points to our
  214.         pop     es                      ; data segment.
  215.         mov     di,offset ds:ourname    ; Destination for scan.
  216.         mov     cx,8+1+3+1              ; Scan up to 13 chars (include 0).
  217.         xor     ax,ax                   ; Scan for zero byte.
  218. repne   scasb                           ; Scan it.
  219.         pop     es                      ; Restore ES.
  220.         mov     ax,8+1+3                ; Max chars for filename.
  221.         sub     ax,cx                   ; Sub renainder in cx.
  222.         mov     cx,ax                   ; Store length.
  223.  
  224.         ; Tell PDS about our return string.
  225.         push    ds                      ; Push far pointer to our return
  226.         mov     ax, offset ds:ourname   ; string on the stack.
  227.         push    ax
  228.         push    cx                      ; Push length of string on the stack.
  229.         push    ds                      ; Push address of our return string 
  230.         mov     ax, offset ds:strdsc    ; descriptor.
  231.         push    ax
  232.         xor     ax,ax                   ; Push a zero to indicate 
  233.         push    ax                      ; a variable length string.
  234.         call    stringassign            ; Call PDS.
  235.  
  236. exit:   ; Now we will restore PDS's DTA.
  237.         push    ds                      ; Save our data segment
  238.         mov     ax, olddtas             ; Place new data segment in AX.
  239.         mov     dx, olddtao             ; Place new offset in DX.
  240.         mov     ds,ax                   ; Set the data segment.
  241.         mov     ah, 1Ah                 ; point DOS to our static DTA
  242.         int     21h                     ; call DOS
  243.         pop     ds                      ; restore our data segment
  244.         ; On return PDS's exspects the string descriptor's address in AX
  245.         mov     ax, offset ds:strdsc    ; 
  246.  
  247.         popf                            ; Restore PDS's flags.
  248.  
  249.         ret
  250. FindFile endp
  251. ;-----------------------------------------------------------------------------
  252. ;
  253. ;
  254. ; OK.  Now that we have all the information we want, we need a way to return
  255. ; it to basic. We will create seperate functions that return the last found
  256. ; file's date, time, size, attribute and the last error. Just to keep things
  257. ; simple we will return everything as a integer.
  258. ;       PDS exspects 2 byte integers to be returned in AX.
  259. ;       PDS exspects 4 byte integers to be returned in DX + AX.
  260. ;
  261. ; WARNING: -------------------
  262. ;       There is no error checking!
  263. ;       If you have not recieved a valid file name from FindFile, or
  264. ;       if you have not called FindFile 
  265. ;       these functions will happily return invalid data !!!!
  266. ;-----------------------------------------------------------------------------
  267. FileError  proc                         ; Lets do the easy ones first
  268.         mov     ax, ourerr              ; Retrieve our error code.
  269.         ret
  270. FileError endp
  271. ;-----------------------------------------------------------------------------
  272. FileFound  proc                         
  273.         mov     ax, found               ; Retrieve number of files found.
  274.         ret
  275. FileFound endp
  276. ;-----------------------------------------------------------------------------
  277. FileAtrb  proc
  278.         xor     ax,ax                   ; Place a zero in AX
  279.         mov     al, ouratr              ; Retrieve our atribute.
  280.         ret     
  281. FileAtrb endp
  282. ;-----------------------------------------------------------------------------
  283. ; **************************************************************************
  284. ; *  NOTE:  Because DOS file size is unsigned and PDS long interger is     *
  285. ; *         signed ---> a negative file size is possible.                  *
  286. ; *         However it would have to be larger than 2 Gigabytes.           *
  287. ; **************************************************************************
  288. FileSize  proc                          ; This one is almost as simple.
  289.         mov     ax, ourlosz             ; Retrieve low order word.
  290.         mov     dx, ourhisz             ; Retrieve high order word.
  291.         ret
  292. FileSize endp
  293. ;-----------------------------------------------------------------------------
  294. FileSec  proc                           
  295.         mov     ax, ourtime             ; Retrieve file time.
  296.         and     ax, 0000000000011111b   ; Mask off the seconds.
  297.         rol     ax,1                    ; DOS stores time in 2 sec increments.
  298.         ret
  299. FileSec endp
  300. ;-----------------------------------------------------------------------------
  301. FileMin  proc                           
  302.         mov     ax, ourtime             ; Retrieve file time.
  303.         and     ax, 0000011111100000b   ; Mask off the minutes.
  304.         mov     cl, 5                   ; We rotate minutes to the right
  305.         ror     ax, cl                  ; 5 bits.
  306.         ret
  307. FileMin endp
  308. ;-----------------------------------------------------------------------------
  309. FileHrs  proc                           
  310.         mov     ax, ourtime             ; Retrieve file time.
  311.         and     ax, 1111100000000000b   ; Mask off the hours
  312.         mov     cl, 5                   ; We rotate hours to the left
  313.         rol     ax, cl                  ; 5 bits.
  314.         ret
  315. FileHrs endp
  316. ;-----------------------------------------------------------------------------
  317. FileDay  proc                           
  318.         mov     ax, ourdate             ; Retrieve file date
  319.         and     ax, 0000000000011111b   ; Mask off the day.
  320.         ret
  321. FileDay endp
  322. ;-----------------------------------------------------------------------------
  323. FileMonth  proc                             
  324.         mov     ax, ourdate             ; Retrieve file date
  325.         and     ax, 0000000111100000b   ; Mask off the month
  326.         mov     cl, 5                   ; We rotate the Month to the right
  327.         ror     ax,cl                   ; 5 bits.
  328.         ret
  329. FileMonth endp
  330. ;-----------------------------------------------------------------------------
  331. FileYear  proc                          
  332.         mov     ax, ourdate             ; Retrieve file date
  333.         and     ax, 1111111000000000b   ; Mask off the year
  334.         mov     cl, 7                   ; We rotate the year to the left
  335.         rol     ax,cl                   ; 7 bits.
  336.         add     ax,1980                 ; Add the base year 1980 to AX.
  337.         ret
  338. FileYear endp
  339. ;-----------------------------------------------------------------------------
  340.         END
  341.